package com.jzo2o.foundations.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.foundations.enums.FoundationStatusEnum;
import com.jzo2o.foundations.mapper.ServeMapper;
import com.jzo2o.foundations.model.domain.Region;
import com.jzo2o.foundations.model.domain.Serve;
import com.jzo2o.foundations.model.domain.ServeItem;
import com.jzo2o.foundations.model.dto.request.ServePageQueryReqDTO;
import com.jzo2o.foundations.model.dto.request.ServeUpsertReqDTO;
import com.jzo2o.foundations.model.dto.response.ServeResDTO;
import com.jzo2o.foundations.service.IRegionService;
import com.jzo2o.foundations.service.IServeItemService;
import com.jzo2o.foundations.service.IServeService;
import com.jzo2o.mysql.utils.PageHelperUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class ServeServiceImpl extends ServiceImpl<ServeMapper, Serve> implements IServeService {


    @Resource
    private IServeItemService serveItemService;
    @Resource
    private IRegionService regionService;


    @Transactional
    @Override
    public void batchAdd(List<ServeUpsertReqDTO> serveUpsertReqDTOList) {
        //1-校验业务逻辑判断：给的区域的服务id是否都是启用状态+同一个区域中不允许出现重复的服务id
        //1.1 查询给的所有服务id的状态是否都是启用   select count(1) from serve_item where id in(?,?) and active_status！=2
        if (CollUtil.isEmpty(serveUpsertReqDTOList)) {
            throw new CommonException("添加的区域服务是不允许为空");
        }
        Set<Long> serveItemIdSet = serveUpsertReqDTOList.stream().map(ServeUpsertReqDTO::getServeItemId).collect(Collectors.toSet());
        if (serveItemService.lambdaQuery().in(ServeItem::getId, serveItemIdSet)
                            .ne(ServeItem::getActiveStatus, FoundationStatusEnum.ENABLE.getStatus()).exists()) {
            throw new ForbiddenOperationException("不允许区域中添加不是启用状态服务项");
        }
        //1.2 同一个区域中不允许出现重复的服务id: 唯一索引的方式约束，只要有相同的服务项存在，则插入数据库会报错

        //2-批量保存区域服务到serve表：给每一个Serve对象填充cityCode
        //2.1 一次性查询所有区域构建Map<Long regionId,String cityCode> regionMap ：select * from region where id in(?,?)
        Set<Long> regionIdSet = serveUpsertReqDTOList.stream().map(ServeUpsertReqDTO::getRegionId).collect(Collectors.toSet());
        Map<Long, String> regionMap = regionService.lambdaQuery().in(Region::getId, regionIdSet).list().stream()
                                                   .collect(Collectors.toMap(Region::getId, Region::getCityCode));

        //2.2 List<ServeUpsertReqDTO>转换List<Serve>循环给给一个serve进行填充cityCode
        List<Serve> serveList = BeanUtil.copyToList(serveUpsertReqDTOList, Serve.class);
        serveList.forEach(serve -> serve.setCityCode(regionMap.getOrDefault(serve.getRegionId(), "")));
        //2.3 批量保存： 如果保存的服务项出现违反唯一约束
        try {
            this.saveBatch(serveList);
        } catch (Exception e) {
            //判断当前补货的异常是否数据库唯一约束的异常，如果是则抛出指定的异常，给出异常消息
            if (e instanceof SQLIntegrityConstraintViolationException) {
                throw new ForbiddenOperationException("不允许在同一个区域中添加的重复服务项");
            }
            throw e;
        }
    }

    @Override
    public PageResult<ServeResDTO> pageServe(ServePageQueryReqDTO servePageQueryReqDTO) {
        return PageHelperUtils.selectPage(servePageQueryReqDTO,
                () -> baseMapper.queryList(servePageQueryReqDTO.getRegionId()));
    }

    @Override
    public void deleteById(Long id) {
        removeById(id);
    }

    @Override
    public void deactivate(Long id) {
        lambdaUpdate().eq(Serve::getId, id).set(Serve::getSaleStatus, 1).update();
    }

    @Override
    public void changeOnHot(Long id) {
        lambdaUpdate().eq(Serve::getId, id).set(Serve::getIsHot, 1).update();
    }

    @Override
    public void disOnDisHot(Long id) {
        lambdaUpdate().eq(Serve::getId, id).set(Serve::getIsHot, 0).update();
    }

    @Override
    public Serve update(Long id, BigDecimal price) {
        //1.更新服务价格
        boolean update = lambdaUpdate()
                .eq(Serve::getId, id)
                .set(Serve::getPrice, price)
                .update();
        if(!update){
            throw new CommonException("修改服务价格失败");
        }
        return baseMapper.selectById(id);
    }
    @Override
    @Transactional
    public Serve onSale(Long id){
        Serve serve = baseMapper.selectById(id);
        if(ObjectUtil.isNull(serve)){
            throw new ForbiddenOperationException("区域服务不存在");
        }
        //上架状态
        Integer saleStatus = serve.getSaleStatus();
        //草稿或下架状态方可上架
        if (!(saleStatus==FoundationStatusEnum.INIT.getStatus() || saleStatus==FoundationStatusEnum.DISABLE.getStatus())) {
            throw new ForbiddenOperationException("草稿或下架状态方可上架");
        }
        //服务项id
        Long serveItemId = serve.getServeItemId();
        ServeItem serveItem = serveItemService.getById(serveItemId);
        if(ObjectUtil.isNull(serveItem)){
            throw new ForbiddenOperationException("所属服务项不存在");
        }
        //服务项的启用状态
        Integer activeStatus = serveItem.getActiveStatus();
        //服务项为启用状态方可上架
        if (!(FoundationStatusEnum.ENABLE.getStatus()==activeStatus)) {
            throw new ForbiddenOperationException("服务项为启用状态方可上架");
        }

        //更新上架状态
        boolean update = lambdaUpdate()
                .eq(Serve::getId, id)
                .set(Serve::getSaleStatus, FoundationStatusEnum.ENABLE.getStatus())
                .update();
        if(!update){
            throw new CommonException("启动服务失败");
        }
        return baseMapper.selectById(id);

    }
}
